﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Globalization;

namespace SharePointFarmInfoTimerJob
{
    class WindowsTaskInfo
    {
        #region Properties

        /// <summary>
        /// CPU usage details
        /// </summary>
        public string CPUUsage
        {
            set;
            get;
        }

        /// <summary>
        /// Memory usage details
        /// </summary>
        public string MemoryUsage
        {
            set;
            get;
        }

        /// <summary>
        /// Memory usage in percentage
        /// </summary>
        public string MemoryUsageInPercentage
        {
            set;
            get;
        }

        /// <summary>
        /// System directory free space in percentage
        /// </summary>
        public string SystemDirectoryFreeSpaceInPercentage
        {
            set;
            get;
        }

        /// <summary>
        /// System directory free space details
        /// </summary>
        public string SystemDirectorySpaceUsage
        {
            set;
            get;
        }

        /// <summary>
        /// Total Memory
        /// </summary>
        public double TotalMemory
        {
            set;
            get;
        }

        /// <summary>
        /// Free Memory
        /// </summary>
        public double FreeMemory
        {
            set;
            get;
        }

        public double DiskFreeSpace
        {
            set;
            get;
        }

        public double DiskCapacity
        {
            set;
            get;
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Constructor - Set the properties
        /// </summary>
        /// <param name="serverName">Server name</param>
        public WindowsTaskInfo(string serverName)
        {
            if (String.IsNullOrEmpty(serverName))
            {
                serverName = Global.LocalMachineName;
            }

            // Configure the connection settings.
            ConnectionOptions options = new ConnectionOptions();
            options.Impersonation = ImpersonationLevel.Impersonate;
            ManagementPath path = new ManagementPath(String.Format(CultureInfo.InvariantCulture, Global.ManagementPath, serverName));
            ManagementScope scope = new ManagementScope(path, options);

            try
            {
                //Connect to the remote machine
                scope.Connect();

                //Query Win32_Processor to get the CPU Usage
                QueryWin32Processor(scope);

                //Query Win32_OperatingSystem for memory and disk space usage
                this.QueryWin32OperatingSystem(scope);
            }
            catch (ManagementException)
            {
                this.SetExceptionMessage(Global.AuthenticationFailureErrorMessage);
            }
            catch (UnauthorizedAccessException)
            {
                this.SetExceptionMessage(Global.UnauthorizedFailureMessage);
            }
            catch (Exception)
            {
                this.SetExceptionMessage(Global.GenericFailureMessage);
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Query Win32_Processor to get the CPU Usage
        /// </summary>
        /// <param name="scope">ManagementScope</param>
        private void QueryWin32Processor(ManagementScope scope)
        {
            //Query Win32_Processor to get the CPU Usage
            ManagementObjectSearcher cPUUsageSearcher = new ManagementObjectSearcher(scope, new ObjectQuery(Global.CPUUsageQuery));
            ManagementObjectCollection cpuUsageMgmtCollection = cPUUsageSearcher.Get();

            foreach (ManagementObject cpuUsageMgmtObj in cpuUsageMgmtCollection)
            {
                //Set the CPU Utilization percentage
                CPUUsage = (Convert.ToDouble(cpuUsageMgmtObj[Global.LoadPercentage]) / 100).ToString();
            }
        }

        /// <summary>
        /// Query the Win32Operating system and collect memory & disk space details
        /// </summary>
        /// <param name="scope">ManagementScope</param>        
        private void QueryWin32OperatingSystem(ManagementScope scope)
        {
            //Query Win32_OperatingSystem for memory and disk space usage
            ManagementObjectSearcher winOSSearcher = new ManagementObjectSearcher(scope, new ObjectQuery(Global.WinOSQuery));
            ManagementObjectCollection winOSMgmtCollection = winOSSearcher.Get();

            foreach (ManagementObject winOSMgmtObj in winOSMgmtCollection)
            {
                this.TotalMemory = Global.ConvertKBToGB(winOSMgmtObj[Global.TotalVisibleMemorySize]);
                this.FreeMemory = Global.ConvertKBToGB(winOSMgmtObj[Global.FreePhysicalMemory]);

                //Set the Memory usage. e.g., 3.27 of 3.82 GB 
                MemoryUsage = String.Format(Global.MemoryUsageStringFormat, (this.TotalMemory - this.FreeMemory), this.TotalMemory);
                //Set the Memory usage in percentage 
                MemoryUsageInPercentage = Math.Round((this.TotalMemory - this.FreeMemory) / this.TotalMemory, 4).ToString();

                //Get the system drive disk information
                ManagementObject disk = new ManagementObject(String.Concat(Global.DeviceId,
                                                                            Global.DoubleQuotes,
                                                                            winOSMgmtObj[Global.SystemDrive],
                                                                            Global.DoubleQuotes));
                disk.Get();

                this.DiskFreeSpace = Global.ConvertBytesToGB(disk[Global.FreeSpace]);
                this.DiskCapacity = Global.ConvertBytesToGB(disk[Global.Size]);

                //Set the system directory free space. e.b., 20 GB free of 80 GB
                this.SystemDirectorySpaceUsage = String.Format(Global.DiskSpaceStringFormat, this.DiskFreeSpace, this.DiskCapacity);
                //Set the system directory free space in percentage
                this.SystemDirectoryFreeSpaceInPercentage = Math.Round(this.DiskFreeSpace / this.DiskCapacity, 4).ToString();
            }
        }

        /// <summary>
        /// Set the exception message
        /// </summary>
        /// <param name="message">message</param>
        private void SetExceptionMessage(string message)
        {
            this.CPUUsage = message;
            this.SystemDirectoryFreeSpaceInPercentage = message;
            this.SystemDirectorySpaceUsage = message;
            this.MemoryUsage = message;
            this.MemoryUsageInPercentage = message;
        }

        #endregion
    }
}
